<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>OpenMesh: Using mesh attributes and traits</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
  $(document).ready(initResizable);
</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="logo_align.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="rwth_vci_rgb.jpg"/></td>
  <td id="projectalign" style="padding-left: 0.5em;">
   <div id="projectname">OpenMesh
   </div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;" 
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
$(document).ready(function(){initNavTree('a04341.html','');});
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div class="header">
  <div class="headertitle">
<div class="title">Using mesh attributes and traits </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>this example shows how to change the data type for positions, normals, colors, and texture,</p>
<p>In the previous tutorial (<a class="el" href="a04340.html">Using standard properties</a>) we learned to use standard properties by calling the appropriate <code>request</code> method. Unlike the custom properties, where the user specifies the data type by passing the type to the handle (e.g. <code>MyMesh::FPropHandleT&lt;</code> <b>int</b>&gt;), the data types of the standard properties are defined by so-called mesh traits. With traits we can customize and extend the mesh data structure. We can do this by changing two important features</p>
<ol type="1">
<li>changing data type for positions, normals, colors, and texture coordinates</li>
<li>extend mesh entities Vertex, Face, Edge, and Halfedge (see tutorial '<a class="el" href="a04342.html">Extending the mesh using traits</a>')</li>
</ol>
<p>Let's start. Every custom traits should derive from the default traits</p>
 <div class="fragment"><div class="line"><span class="keyword">struct </span><a class="code" href="a01881.html">MyTraits</a> : <a class="code" href="a02469.html">OpenMesh::DefaultTraits</a></div></div><!-- fragment --></p>
<p>As mentioned, we can change the basic data types for the basic types <code><a class="el" href="a02389.html#aed10fb4dfb536b53a5e20c8f2442eadf" title="Coordinate type. ">MyMesh::Point</a></code>, <code><a class="el" href="a02389.html#a3570fd132d1ac589b380485cf59c9e0b" title="Normal type. ">MyMesh::Normal</a></code>, <code><a class="el" href="a02389.html#af0d8129bf1a819c468c6edcb13b5203b" title="Color type. ">MyMesh::Color</a></code>, and <code>MyMesh::TexCoord</code>. We can use the provided vector class or we use a different one from another library. Here we simply replace the default type <code><a class="el" href="a01233.html#aeb4e43a28974a16e6131fd93eef1ebfe" title="3-float vector ">OpenMesh::Vec3f</a></code> (defined in the <code><a class="el" href="a02469.html" title="Base class for all traits. ">OpenMesh::DefaultTraits</a></code>) for positions and normals with <code><a class="el" href="a01233.html#a0d0d12b328b4ed0facca69be164cb8be" title="3-double vector ">OpenMesh::Vec3d</a></code> </p>
<p><div class="fragment"><div class="line">  <span class="keyword">typedef</span> <a class="code" href="a02001.html">OpenMesh::Vec3d</a> Point;</div><div class="line">  <span class="keyword">typedef</span> <a class="code" href="a02001.html">OpenMesh::Vec3d</a> <a class="code" href="a01238.html#ab78a93560926cd2f9958cb028f7ea96da213616dd2e4d9744d863587001a77988">Normal</a>;</div></div><!-- fragment --></p>
<p>(In general it's better to have the same scalar type for the point and normal vector, for instance <code>double</code> in this case. Otherwise we have to cast quite a lot depending on the implementation of the vector class.)</p>
<p>Be aware that these settings overwrite the ones of the parent traits class! As we usually derive from the DefaultTraits let's have a close look.</p>
<p>Actually the struct <code><a class="el" href="a02469.html" title="Base class for all traits. ">OpenMesh::DefaultTraits</a></code> is merely empty. It solely defines the types for <code>Point</code>, <code>Normal</code>, <code>TexCoord</code>, and <code>Color</code> and one attribute, that we used implicitly all the time:</p>
<p><div class="fragment"><div class="line">  <span class="comment">// HalfedgeAttributes( OpenMesh::Attributes::PrevHalfedge );</span></div></div><!-- fragment --></p>
<p>The attribute <code>PrevHalfedge</code> is different, as it does not control a property. Yet it has a great impact on the resulting mesh type, as it adds additional information to the halfedge structure. The impact is twofold:</p>
<ol type="1">
<li>fast access to previous halfedge</li>
<li>increase of memory consumption</li>
</ol>
<p>Using this feature depends highly on our needs. One situation where the previous halfedges are quite handy, is the mesh member function add_face(). The execution time for the member function drops dramatically, when the information about the previous halfedge is available. Usually we want to have this information. But if not, because we must save memory, we can easily remove it with</p>
<p><div class="fragment"><div class="line">  <span class="comment">// HalfedgeAttributes( OpenMesh::Attributes::None );</span></div></div><!-- fragment --></p>
<p>Then we need 8 bytes less per edge, which can be quite a lot as one can derive from the Euler formula <b style="background-color:#FFFFFF;">( <img class="formulaInl" alt="$V-E+F=2 (1-g)$" src="form_0.png"/>)</b>, that for a regular triangle meshes with genus <b style="background-color:#FFFFFF;"> <img class="formulaInl" alt="$g=0$" src="form_1.png"/></b> the number of edges <b style="background-color:#FFFFFF;"> <img class="formulaInl" alt="$E$" src="form_2.png"/></b> is approximately three times the number of vertices <b style="background-color:#FFFFFF;"> <img class="formulaInl" alt="$V$" src="form_3.png"/>: <img class="formulaInl" alt="$ E \approx 3 \cdot V$" src="form_4.png"/></b>.</p>
<p>The complete source looks like this:</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &lt;iostream&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;typeinfo&gt;</span></div><div class="line"><span class="comment">// --------------------</span></div><div class="line"><span class="preprocessor">#include &lt;OpenMesh/Core/IO/MeshIO.hh&gt;</span></div><div class="line"></div><div class="line"><span class="preprocessor">#include &lt;OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;OpenMesh/Core/Geometry/VectorT.hh&gt;</span></div><div class="line"></div><div class="line"><span class="preprocessor">#ifndef DOXY_IGNORE_THIS</span></div><div class="line"></div><div class="line"><span class="comment">// Define my personal traits</span></div><div class="line"><span class="keyword">struct </span><a class="code" href="a01881.html">MyTraits</a> : <a class="code" href="a02469.html">OpenMesh::DefaultTraits</a></div><div class="line">{</div><div class="line">  <span class="comment">// Let Point and Normal be a vector of doubles</span></div><div class="line">  <span class="keyword">typedef</span> <a class="code" href="a02001.html">OpenMesh::Vec3d</a> Point;</div><div class="line">  <span class="keyword">typedef</span> <a class="code" href="a02001.html">OpenMesh::Vec3d</a> Normal;</div><div class="line"></div><div class="line">  <span class="comment">// Already defined in OpenMesh::DefaultTraits</span></div><div class="line">  <span class="comment">// HalfedgeAttributes( OpenMesh::Attributes::PrevHalfedge );</span></div><div class="line">  </div><div class="line">  <span class="comment">// Uncomment next line to disable attribute PrevHalfedge</span></div><div class="line">  <span class="comment">// HalfedgeAttributes( OpenMesh::Attributes::None );</span></div><div class="line">  <span class="comment">//</span></div><div class="line">  <span class="comment">// or</span></div><div class="line">  <span class="comment">//</span></div><div class="line">  <span class="comment">// HalfedgeAttributes( 0 );</span></div><div class="line">};</div><div class="line"></div><div class="line"><span class="preprocessor">#endif</span></div><div class="line"></div><div class="line"><span class="comment">// Define my mesh with the new traits!</span></div><div class="line"><span class="keyword">typedef</span> <a class="code" href="a02377.html">OpenMesh::TriMesh_ArrayKernelT&lt;MyTraits&gt;</a>  MyMesh;</div><div class="line"></div><div class="line"><span class="comment">// ------------------------------------------------------------------ main ----</span></div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main(<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span> **argv)</div><div class="line">{</div><div class="line">  MyMesh mesh;</div><div class="line"></div><div class="line">  <span class="keywordflow">if</span> (argc!=2)</div><div class="line">  {</div><div class="line">    std::cerr &lt;&lt; <span class="stringliteral">&quot;Usage: &quot;</span> &lt;&lt; argv[0] &lt;&lt; <span class="stringliteral">&quot; &lt;input&gt;\n&quot;</span>;</div><div class="line">    <span class="keywordflow">return</span> 1;</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="comment">// Just make sure that point element type is double</span></div><div class="line">  <span class="keywordflow">if</span> ( <span class="keyword">typeid</span>( <a class="code" href="a02621.html#a127a4d7ca521ed3254cd801917ee67d4">OpenMesh::vector_traits&lt;MyMesh::Point&gt;::value_type</a> ) </div><div class="line">       != <span class="keyword">typeid</span>(<span class="keywordtype">double</span>) )</div><div class="line">  {</div><div class="line">    std::cerr &lt;&lt; <span class="stringliteral">&quot;Ouch! ERROR! Data type is wrong!\n&quot;</span>;</div><div class="line">    <span class="keywordflow">return</span> 1;</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="comment">// Make sure that normal element type is double</span></div><div class="line">  <span class="keywordflow">if</span> ( <span class="keyword">typeid</span>( <a class="code" href="a02621.html#a127a4d7ca521ed3254cd801917ee67d4">OpenMesh::vector_traits&lt;MyMesh::Normal&gt;::value_type</a> ) </div><div class="line">       != <span class="keyword">typeid</span>(<span class="keywordtype">double</span>) )</div><div class="line">  {</div><div class="line">    std::cerr &lt;&lt; <span class="stringliteral">&quot;Ouch! ERROR! Data type is wrong!\n&quot;</span>;</div><div class="line">    <span class="keywordflow">return</span> 1;</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="comment">// Add vertex normals as default property (ref. previous tutorial)</span></div><div class="line">  mesh.request_vertex_normals();</div><div class="line"></div><div class="line">  <span class="comment">// Add face normals as default property</span></div><div class="line">  mesh.request_face_normals();</div><div class="line"></div><div class="line">  <span class="comment">// load a mesh</span></div><div class="line">  <a class="code" href="a02029.html">OpenMesh::IO::Options</a> opt;</div><div class="line">  <span class="keywordflow">if</span> ( ! <a class="code" href="a01236.html#ac417960ec28ffdd7e7003a2b1ebb2d1c">OpenMesh::IO::read_mesh</a>(mesh,argv[1], opt))</div><div class="line">  {</div><div class="line">    std::cerr &lt;&lt; <span class="stringliteral">&quot;Error loading mesh from file &quot;</span> &lt;&lt; argv[1] &lt;&lt; std::endl;</div><div class="line">    <span class="keywordflow">return</span> 1;</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="comment">// If the file did not provide vertex normals, then calculate them</span></div><div class="line">  <span class="keywordflow">if</span> ( !opt.check( <a class="code" href="a02029.html#a9f4f797b08c045b611eaa6f8d149da21ad989c6d671050e12953b648c4c72dded">OpenMesh::IO::Options::VertexNormal</a> ) &amp;&amp;</div><div class="line">       mesh.has_face_normals() &amp;&amp; mesh.has_vertex_normals() )</div><div class="line">  {</div><div class="line">    <span class="comment">// let the mesh update the normals</span></div><div class="line">    mesh.<a class="code" href="a02389.html#a601f21014e50bd5a2243b0e4849c9c14">update_normals</a>();</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="comment">// move all vertices one unit length along it&#39;s normal direction</span></div><div class="line">  <span class="keywordflow">for</span> (MyMesh::VertexIter v_it = mesh.vertices_begin();</div><div class="line">       v_it != mesh.vertices_end(); ++v_it)</div><div class="line">  {</div><div class="line">    std::cout &lt;&lt; <span class="stringliteral">&quot;Vertex #&quot;</span> &lt;&lt; *v_it &lt;&lt; <span class="stringliteral">&quot;: &quot;</span> &lt;&lt; mesh.point( *v_it );</div><div class="line">    mesh.set_point( *v_it, mesh.point(*v_it)+mesh.normal(*v_it) );</div><div class="line">    std::cout &lt;&lt; <span class="stringliteral">&quot; moved to &quot;</span> &lt;&lt; mesh.point( *v_it ) &lt;&lt; std::endl;</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="keywordflow">return</span> 0;</div><div class="line">}</div></div><!-- fragment --> </div></div><!-- contents -->
</div><!-- doc-content -->
<hr>
<address>
<small>
<a href="http://www.rwth-graphics.de" style="text-decoration:none;">
</a>
Project <b>OpenMesh</b>, 
&copy;&nbsp; Computer Graphics Group, RWTH Aachen.
Documentation generated using 
<a class="el" href="http://www.doxygen.org/index.html">
<b>doxygen</b>
</a>.
</small>
</address>
</body>
</html>
